using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Diagnostics;
using GoodStuff;

namespace GoodStuff
{
    public class GoodObjectBuilder
    {
        XmlTextReader _reader;

        protected void ParseElement()
        {
            XmlNodeType currentNodeType = _reader.NodeType;
            string currentNodeName = _reader.Name;
        }

        public static object Instantiate(string AssemblyName, string TypeName)
        {
            return Instantiate(AssemblyName, AssemblyName, TypeName);
        }

        public static object Instantiate(string AssemblyName, string Namespace, string TypeName)
        {
            Assembly a = Assembly.LoadFrom(AssemblyName + ".dll");
            Type t = a.GetType(Namespace + "." + TypeName);
            ConstructorInfo ci = t.GetConstructor(System.Type.EmptyTypes);
            object o = ci.Invoke(null);
            return o;
        }

        public static void ConnectEvent(object EventSource, string EventName, object EventListner, string HandlerName)
        {
            Type tSource = EventSource.GetType();
            EventInfo ei = tSource.GetEvent(EventName);
            Type evDelegate = ei.EventHandlerType;

            Type tHandler = EventListner.GetType();
            MethodInfo mi = tHandler.GetMethod(HandlerName);
            
            Delegate d = Delegate.CreateDelegate(evDelegate, EventListner, HandlerName);

            ei.AddEventHandler(EventSource, d);
        }

        public static void ConnectProperty(object Target, string PropertyName, object Value)
        {
            Type t = Target.GetType();
            PropertyInfo pi = t.GetProperty(PropertyName);
            IGoodProperty iValue = Value as IGoodProperty;
            pi.SetValue(Target, iValue, null);
        }

        public static void SetValue(IGoodProperty Parameter, IConvertible Value)
        {
            Parameter.Set(Value);
        }

        public static IGoodProperty PropertyFactory(string GenericType)
        {
            string typeName = "System." + GenericType;
            Type[] gType = new Type[1] { Type.GetType(typeName) };
            Type t;
            Assembly a = Assembly.LoadFrom("GoodStuff.dll");
            Type parameterType = a.GetType("GoodStuff.GoodProperty`1");

            t = parameterType.MakeGenericType(gType);

            ConstructorInfo ci = t.GetConstructor(new Type[0]);
            IGoodProperty c = (IGoodProperty)ci.Invoke(null);

            return c;
        }

        public static void ReadFile(string path)
        {
            XmlTextReader r = new XmlTextReader(path);

            //Type goodVariableType = Type.GetType("GoodStuff.GoodVariable`1");
            //Type goodNumericVariableType = Type.GetType("GoodStuff.GoodNumericVariable`1");

            while (r.Read())
            {
                string s;
                int j;

                if (r.NodeType == XmlNodeType.Element)
                    switch (r.Name)
                    {
                        case "GoodObject":
                            {
                                string name = r.GetAttribute("Name");
                                string type = r.GetAttribute("Type");
                                string assembly = r.GetAttribute("Assembly");
                                ObjectManager.Add(name, Instantiate(assembly, type));
                                break;
                            }

                        case "Property":
                            {
                                string name = r.GetAttribute("Name");
                                string type = r.GetAttribute("Type");
                                IGoodProperty gp = PropertyFactory(type);
                                r.Read();
                                gp.Set(r.Value);
                                ObjectManager.Add(name, gp);
                                break;
                            }

                        case "Connection":
                            {
                                string from = r.GetAttribute("From");
                                string eventName = r.GetAttribute("Event");
                                string to = r.GetAttribute("To");
                                string handler = r.GetAttribute("Handler");

                                object fromObject = ObjectManager.Get(from);
                                object toObject = ObjectManager.Get(to);

                                ConnectEvent(fromObject, eventName, toObject, handler);
                            }
                            break;

                        case "Reference":
                            {
                                string from = r.GetAttribute("From");
                                string key = r.GetAttribute("PropertyName");
                                string to = r.GetAttribute("To");

                                object fromObject = ObjectManager.Get(from);
                                object toObject = ObjectManager.Get(to);

                                ConnectProperty(fromObject, key, toObject);
                            }
                            break;

                        case "Control":
                            {
                                string windowName = r.GetAttribute("Window");
                                string controlName = r.GetAttribute("Control");
                                GoodWindow gw = ObjectManager.Get(windowName) as GoodWindow;
                                IGoodControl gc = ObjectManager.Get(controlName) as IGoodControl;
                                gw.Add(gc.Control);
                            }
                            break;
                    }


                //if ((r.NodeType == XmlNodeType.Element) && (r.Name == "GoodObject"))
                //{
                //}
                //if ((r.NodeType == XmlNodeType.Element) && (r.Name == "Property"))
                //{
                //    string key = r.GetAttribute("Key");
                //    string name = r.GetAttribute("Name");
                //    string type = r.GetAttribute("Key");
                //    string reference = r.GetAttribute("Key");

                

                //    switch (r.GetAttribute("Type"))
                //    {
                //        case "instanceName":
                //            break;

                //        default:
                //            string typeName = "System." + r.GetAttribute("Type");
                //            Type[] gvType = new Type[1] { Type.GetType(typeName) };
                //            Type t;

                //            if (gvType[0].GetInterface("IConvertible") == null)
                //                t = goodVariableType.MakeGenericType(gvType);
                //            else
                //                t = goodNumericVariableType.MakeGenericType(gvType);



                //            ConstructorInfo ci = t.GetConstructor(gvType);
                //            object[] initialValue = new object[1] { r.ReadElementContentAs(gvType[0], null) };
                //            IGoodVariable c = (IGoodVariable)ci.Invoke(initialValue);
                //            PropertyInfo pi = t.GetProperty("blort");
                //            MethodInfo mi = pi.GetSetMethod();
                //            //                  mi.Invoke(c, params);
                //            break;
                //    }
                //}

                //Trace.WriteLine(r.NodeType.ToString());
                //for (int i = 0; i < r.AttributeCount; ++i)
                //{
                //    string attr = r.GetAttribute(i);
                //}

            }
        }
    }
}
